package cn.haoma.base.socket;


import android.os.Handler;
import android.os.Message;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import cn.haoma.base.socket.inf.Messenger;
import cn.haoma.base.socket.inf.SocketHandler;
import cn.haoma.base.socket.inf.ConnectionStatus;
import cn.haoma.base.socket.inf.ConnectionStatusListener;
import cn.haoma.base.socket.inf.MsgCallBack;
import cn.haoma.base.socket.inf.MsgListener;

public class MsgHandler implements SocketHandler {

    public static final int ON_MSG_RESEIVE = 3;
    public static final int ON_MSG_SEND = 1;
    public static final int ON_CONNECTED = 2;
    public static final int ON_DISCONNECTED = 4;

    private static Messenger messenger;
    private static MsgHandler msgHandler;
    /**
     * 有新消息时集合里的handler会把消息传出去，数据放在Message的obj中what为1，类型为String
     * 网络断开返回NET_DISCONNECTED
     */
    private static HashMap<Integer, MsgCallBack> msgCallBackMap = new HashMap();
    private static HashMap<MsgCallBack, Msg> callBackMsgMap = new HashMap<>();
    /**
     *
     */
    private static HashSet<MsgListener> msgListenerList = new HashSet();
    private static HashSet<ConnectionStatusListener> statusListenerList = new HashSet();
    private static Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case ON_MSG_RESEIVE:
                    Msg msg = (Msg) message.obj;
                    MsgCallBack callBack = msgCallBackMap.get(msg.id);// 根据Msg的Id获取发消息时对应的Handler
                    if (null != callBack) {
                        msgCallBackMap.remove(msg.id);
                        callBack.onMsgSend(msg);
                    } else {// 服务器推送的消息
                        for (MsgListener listener : msgListenerList) {
                            if (listener.onMsgReceived(msg)) {
                                break;
                            }
                        }
                        // 告诉服务器消息收到，如果服务器没收到此消息，下次可能重发此消息
                        if (msg.needConfirm) {
                            Msg ack = new Msg();
                            ack.cmd = MsgProtocol.CMD_CONFIRM;
                            ack.id = msg.id;
                            messenger.sendMessage(ack);
                        }
                    }
                    break;
                case ON_MSG_SEND:
                    break;
                case ON_CONNECTED:
                    for (ConnectionStatusListener listener : statusListenerList) {
                        listener.onStatusChanged(ConnectionStatus.STATUS_CONNECTED);
                    }
                    break;
                case ON_DISCONNECTED:
                    for (Map.Entry<Integer, MsgCallBack> entry : msgCallBackMap.entrySet()) {
                        MsgCallBack call = entry.getValue();
                        Msg m = callBackMsgMap.get(call);
                        call.onMsgFailToSend(m);
                        callBackMsgMap.remove(m);
                    }
                    msgCallBackMap.clear();
                    for (ConnectionStatusListener listener : statusListenerList) {
                        listener.onStatusChanged(ConnectionStatus.STATUS_DISCONNECTED);
                    }
                    break;
            }


        }
    };

    private MsgHandler() {

    }

    public static MsgHandler getInstance(Messenger m) {
        if (null == msgHandler) {
            msgHandler = new MsgHandler();
            messenger = m;

        }
        return msgHandler;
    }

    @Override
    public void onMsgReceived(Msg msg) {
        Message.obtain(handler, ON_MSG_RESEIVE, msg).sendToTarget();
    }

    @Override
    public void onRegistMsgListener(MsgListener msgListener) {
        msgListenerList.add(msgListener);
    }

    @Override
    public void onRegistStatusListener(ConnectionStatusListener connectionStatusListener) {
        statusListenerList.add(connectionStatusListener);
    }

    @Override
    public void onSendMsg(Msg msg, MsgCallBack msgCallBack) {
        if (null != msgCallBack) {
            msgCallBackMap.put(msg.id, msgCallBack);
            callBackMsgMap.put(msgCallBack, msg);
        }
    }

    @Override
    public void onSocketClosed() {
        Message.obtain(handler, ON_DISCONNECTED).sendToTarget();
    }

    @Override
    public void onSocketConnected() {
        Message.obtain(handler, ON_CONNECTED).sendToTarget();
    }

    @Override
    public void onUnregistMsgListener(MsgListener listener) {
        msgListenerList.remove(listener);
    }

    @Override
    public void onUnregistStatusListener(ConnectionStatusListener listener) {
        statusListenerList.remove(listener);
    }
}
